#!/usr/bin/perl

#    D-HUD - DStar Repeater and Reflector Heads up Display
#    Copyright (C) 2011>  Andrew Ragusa (KC9EVU) and Corey Shields (KB9JHU)
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#    ajragusa@gmail.com cshields@gmail.com


use strict;
use CGI;
use JSON;
use DBI;
use Data::Dumper;

our %methods;
our $dbh;


if(!defined($dbh)){
    my $pass="qsl2k9iu";
    $dbh = DBI->connect("dbi:mysql:dbname=dsm","root",$pass) or die "Unable to connect to database: $!\n";

=head2 get_users_tx
	
=cut

sub get_users_tx{
    my $cgi = shift;
    my $call = $cgi->param('call');
    my $start_time = $cgi->param('start');

    if(!defined($call)){
	return {'error' => "No Call specified"};
    }

    if(!defined($start_time)){
	$start_time = time - (24 * 60 * 60);
    }

    my $str = "select * from LastXmt where SrcStn = ? and UNIX_TIMESTAMP(StartTime) > ?";
    my $sth = $dbh->prepare($str);
    $sth->execute($call,$start_time);
    
    my @data;
    while(my $row = $sth->fetchrow_hashref()){
	my $tmp;
	$tmp->{'call'} = $row->{'ScrStn'};
	$tmp->{'message'} = $row->{'SrcStnExt'};
	$tmp->{'Time'} = $row->{'StartTime'};
	$tmp->{'duration_sec'} = $row->{'duration'} / 100;
	$tmp->{'UR'} = $row->{'DestStn'};
	$tmp->{'RPT1'} = $row->{'SrcRptr'};
	$tmp->{'RPT2'} = $row->{'DestRptr'};
	push(@data,$tmp);
    }

    return \@data;
}

$methods{'get_users_tx'} = \&get_users_tx;

=head2 get_users_time

=cut


sub get_users_time{
    my $cgi = shift;
    my $call = $cgi->param('call');
    my $start_time = $cgi->param('start');

    if(!defined($call)){
	warn "No Call specified\n";
	return {'error' => 'No Call Specified'};
    }

    if(!defined($start_time)){
	$start_time = time - (24 * 60 * 60);
    }

    my $str = "select duration from LastXmt where SrcStn = ? and UNIX_TIMESTAMP(StartTime) > ?";
    my $sth = $dbh->prepare($str) or die "Unable to prepare SQL: $!\n";
    $sth->execute($call,$start_time) or die "Unable to prepare SQL: $!\n";;

    my $time=0;
    while(my $trans = $sth->fetchrow_hashref()){
	$time += $trans->{'duration'};
    }
    return {'total_minutes' => (($time/1000)/60)};
}

$methods{'get_users_time'} = \&get_users_time;


=head2 get_port_status

=cut

sub get_port_status{
    my $cgi = shift;
    my @data;
    my $a = "unlinked";
    my $b = "unlinked";
    my $c = "unlinked";

    my $results = `grep "Linked to" /dstar/tmp/status`;

    my @res = split('\n',$results);
    foreach my $result (@res){
	$result =~ /call (.{8}) status Linked to (\w)/;
	if($2 eq 'A'){
	    $a = $1;
	}elsif($2 eq 'B'){
	    $b = $1;
	}elsif($2 eq 'C'){
	    $c = $1;
	}
    }

    push(@data,{port => 'A', status => $a});
    push(@data,{port => 'B', status => $b});
    push(@data,{port => 'C', status => $c});
    
    return \@data;
}

$methods{'get_port_status'} = \&get_port_status;


=head2 get_usage

=cut

sub get_usage{
    my $cgi = shift;
    my $time_frame = $cgi->param('time_frame');

    if(!defined($time_frame)){
	warn "TimeFrame not defined\n";
	return undef;
    }

    my $callsign = $cgi->param('callsign');
    my $sth;

    if(!defined($callsign)){
	
	my $str = "select unix_timestamp(StartTime) as epoch,LastXmt.* from LastXmt where UNIX_TIMESTAMP(StartTime) > (UNIX_TIMESTAMP(NOW()) - " . $time_frame . ")";
	
	$sth = $dbh->prepare($str) or die "Unable to prepare SQL: $!\n";
	$sth->execute() or die "Unable to prepare SQL: $!\n";;
    }else{
	my $str = "select unix_timestamp(StartTime) as epoch,LastXmt.* from LastXmt where UNIX_TIMESTAMP(StartTime) > (UNIX_TIMESTAMP(NOW()) - " . $time_frame . ") and SrcStn = ?";
	$sth = $dbh->prepare($str) or die "Unable to prepare SQL: $!\n";
	$sth->execute($callsign) or die "Unable to execute SQL: $!\n";
    }

    my @stuff;
    my $time = time();
    #group into 1hr chunks?
    while(my $tmp = $sth->fetchrow_hashref()){
	push(@stuff,$tmp);
    }

    my $time_count = $time - $time_frame;
    my @data;
    my $i;
    my $usage;
    my $j=0;
    my $interval;
    if($time_frame <= 86400){
	$interval = 60 * 60;
    }else{
	$interval = 60 * 60 * 24;
    }

    while($time_count < $time){
	$time_count++;
	$i++;

	while($stuff[$j]->{'epoch'} < $time_count && $j < $#stuff){
	    $usage += $stuff[$j]->{'Duration'};
	    $j++;
	}

	if($i == $interval){
	    push(@data,{timestamp => $time_count, usage => (($usage / 1000) / 60)});
	    $i=0;
	    $usage = 0;
	}
    }

    return \@data;
}

$methods{'get_usage'} = \&get_usage;

=head2 get_unique_callsigns_per_day

=cut

sub get_unique_callsigns_per_day{
    my $cgi = shift;
    my $total_days = $cgi->param('days');
    if(!defined($total_days)){
	$total_days = 30;
    }
    
    my $str = "select count(distinct(SrcStn)) as count from LastXmt where unix_timestamp(StartTime) > ? and unix_timestamp(StartTime) < ?";
    my $sth = $dbh->prepare($str) or die "Unable to prepare SQL: $!\n";

    my @data;
    for(my $i=0;$i<$total_days;$i++){
	my $start_time = time() - (($i+1) * 86400);
	my $end_time = time() - ($i * 85400);
	$sth->execute($start_time,$end_time) or die "Unable to execute SQL: $!\n";
	my $row = $sth->fetchrow_hashref();
	push(@data,{timestamp => $start_time, unique_calls => $row->{'count'}});
    }

    return \@data;
}

$methods{'get_unique_callsigns_per_day'} = \&get_unique_callsigns_per_day;

=head2 get_top_talkers

=cut

sub get_top_talkers{
    my $cgi = shift;
    my $total_to_show = $cgi->param('total_to_show');
    if(!defined($total_to_show)){
	$total_to_show = 5;
    }
    my $str = "select distinct(SrcStn) from LastXmt where unix_timestamp(StartTime) > ?";
    my $sth = $dbh->prepare($str) or die "Unable to prepare SQL: $!\n";
    $sth->execute((time() - 30 * 86400)) or die "Unable to execute SQL: $!\n";
    
    my @calls;
    while(my $row = $sth->fetchrow_hashref()){
	$cgi->param('call',$row->{'SrcStn'});
	$cgi->param('start', time() - 30 * 86400);
	$row->{'total_minutes'} = get_users_time($cgi)->{'total_minutes'};
	push(@calls,$row);
    }

    @calls = sort {$a->{'total_minutes'} <=> $b->{'total_minutes'} } @calls;

    my @data;
    
    for(my $i=0;$i<$total_to_show;$i++){
	push(@data,$calls[$#calls - $i -1]);
    }

    
    return \@data;

}

$methods{'get_top_talkers'} = \&get_top_talkers;

=head2 get_recent_users 

=cut

sub get_recent_users{
    my $cgi = shift;
    my $str = "select unix_timestamp(ReportTime) as timestamp,LastHeard.* from LastHeard where unix_timestamp(ReportTime) > ? order by unix_timestamp(ReportTime) desc";
    my $sth = $dbh->prepare($str) or die "Unable to prepare SQL: $!\n";
    $sth->execute(time() - 86400) or die "Unable to prepare SQL: $!\n";
    
    my @data;
    while(my $row = $sth->fetchrow_hashref()){
	$row->{'call_sign'} = $row->{'StationCall'};
	$row->{'SrcRptr'} =~ /.{7}(\w)/;
	$row->{'port'} = $1;
	push(@data,$row);
    }

    return \@data;
}

$methods{'get_recent_users'} = \&get_recent_users;

=head2 get_log

=cut

sub get_log{
    my $cgi = shift;
    my $callsign = $cgi->param('callsign');
    my $sth;
    if(!defined($callsign)){
	my $str = "select * from LastXmt where unix_timestamp(StartTime) > ? order by unix_timestamp(StartTime) desc";
	$sth = $dbh->prepare($str) or die "Unable to prepare SQL: $!\n";
	$sth->execute(time() - 86400) or die "Unabel to execute SQL: $!\n";
    }else{
	my $str = "select * from LastXmt where unix_timestamp(StartTime) > ? and SrcStn = ? order by unix_timestamp(StartTime) desc";
	$sth = $dbh->prepare($str) or die "Unable to prepare SQL: $@\n";
	$sth->execute(time() - 86400, $callsign) or die "Unable to execute SQL: $!\n";
    }
    my @data;
    while(my $row = $sth->fetchrow_hashref()){
	push(@data,$row);
    }

    return \@data;
    
}

$methods{'get_log'} = \&get_log;

=head2 get_all_users

=cut

sub get_all_users{
    my $cgi = shift;
    my $str = "select distinct(SrcStn) as call_sign, SrcStnExt as message from LastXmt";
    my $sth = $dbh->prepare($str);
    $sth->execute();
    
    my @data;
    while(my $row = $sth->fetchrow_hashref()){
	push(@data,$row);
    }

    return \@data;
}

$methods{'get_all_users'} = \&get_all_users;

=head2 help

=cut

sub help{
    
}

$methods{'help'} = \&help;
}
=head2 main

=cut


sub main{
    my $cgi = new CGI;

    my $method = $cgi->param("method");
    my $results;

    if(!defined($method)){
        $results->{'error'} = "Method not specified";
    }elsif (!exists $methods{$method}){
        $results->{'error'} = "Unknown method - '$method'.";
    }else{
        $results->{'results'} = $methods{$method}($cgi);
    }
    
    print $cgi->header(-type=>"application/json");
    print to_json($results);

}


main();
